package com.spring.processor;

import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.stream.Stream;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;

public class ApolloBeanPostProcessor implements BeanClassLoaderAware, BeanFactoryPostProcessor,EnvironmentAware{
	private ClassLoader classLoader;
	
	public static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

	public static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

	private Environment environment;
	@Override
	public void setBeanClassLoader(ClassLoader classLoader) {
		this.classLoader = classLoader;
	}

	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		InputStream inputStream = classLoader.getResourceAsStream("apollo.properties");
		Properties pro = new Properties();
		try {
			pro.load(inputStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		String[] beanNames = beanFactory.getBeanDefinitionNames();
		for (String beanName : beanNames) {
			Object obj = beanFactory.getBean(beanName);
			Stream.of(obj.getClass().getDeclaredFields()).forEach(field -> {
				if (field.isAnnotationPresent(Value.class)) {
					String value = field.getAnnotation(Value.class).value();
					field.setAccessible(true);
					try {
						field.set(obj,
								pro.get(value.substring(value.indexOf(DEFAULT_PLACEHOLDER_PREFIX) + 2,
										value.indexOf(DEFAULT_PLACEHOLDER_SUFFIX))));
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		}
	}

	@Override
	public void setEnvironment(Environment environment) {
		this.environment = environment ;
	}
}
